package heap

import "jvm/nzpJvm/classfile"

// 接口方法的符号引用
type InterfaceMethodRef struct {
	MemberRef
	interfaceMethod *Method
}

// 新建一个接口方法符号引用
func newInterfaceMethodRef(pool *ConstantPool, info *classfile.ConstantInterfaceMethodrefInfo) Constant {
	interfaceMethod := &InterfaceMethodRef{}
	interfaceMethod.cp=pool
	interfaceMethod.copyMemberRefInfo(&info.ConstantMemberRefInfo)
	return interfaceMethod
}


// 根据接口方法的符号引用获取直接引用
func (self *InterfaceMethodRef) ResolveInterfaceMethod() *Method {
	// 如果还没有解析过，就解析
	if self.interfaceMethod == nil {
		self.ResolveInterfaceMethodRef()
	}
	return self.interfaceMethod
}

// 将接口方法的符号引用转换为直接引用
func (self *InterfaceMethodRef) ResolveInterfaceMethodRef() {
	// 当前类，也就是触发解析的类
	currentClass := self.cp.class
	// 目标类，也就是定义这个方法的类，对于接口方法来说，它是一个接口
	interf := self.ResolveClass()
	if !interf.IsInterface() {
		// 解析接口方法，如果这个类不是接口，就报错
		panic("java.lang.IncompatibleClassChangeError")
	}
	method := lookupInterfaceMethod(interf, self.name, self.descriptor)
	if method == nil {
		panic("java.lang.NoSuchMethodError")
	}

	// 判断当前类是否可以访问到这个方法
	if !method.isAccessibleTo(currentClass) {
		panic("java.lang.IllegalAccessError")
	}
	self.interfaceMethod = method
}

// 查找接口方法
func lookupInterfaceMethod(interf *Class, name string, descriptor string) *Method {
	// 遍历这个接口中的所有方法
	for _, method := range interf.methods {
		if method.name == name && method.descriptor == descriptor {
			return method
		}
	}
	// 没找到，查找父接口
	return LookupMethodInInterface(interf.interfaces,name,descriptor)
}
